﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#ifndef __SERVER_MAP_H__
#define __SERVER_MAP_H__

#pragma once

#include "datadef.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 服务器信息结构定义, 粗略统计使用, 未做多线程数据保护
struct tagSERVER_INFO : public tagSERVER_STATUS
{
public:
    tagSERVER_INFO(void);
    ~tagSERVER_INFO(void);
    /// 按特定状态要求读写
    /// @param[in] CStream& Stream数据流
    /// @param[in] UShort us特定状态
    /// @reremarks 默认只对注册数据状态, 同步更新状态和注销状态进行操作
    void     Info(CStream& Stream, UShort us = (UShort)STATUSU_XLINKSYNC);
    /// 拷贝数据
    /// @param[in] tagSERVER_STATUS& ss 服务器数据
    void     Copy(const tagSERVER_STATUS& ss);
    /// 服务器组统计增加一台同类型服务器, 连接量和在线量增加情况
    /// @param[in] tagSERVER_STATUS& ss 增加的服务器数据
    void     Incr(const tagSERVER_STATUS& ss);
    /// 服务器组统计一台同类型服务器数据更新, 连接量和在线量变化情况(差值变化)
    /// @param[in] tagSERVER_STATUS& ssIncr 服务器更新以后的数据
    /// @param[in] tagSERVER_STATUS& ssDecr 服务器更新以前的数据
    void     Diff(const tagSERVER_STATUS& ssIncr, const tagSERVER_STATUS& ssDecr);
    /// 服务器组统计减少一台同类型服务器, 连接量和在线量减少情况
    /// @param[in] tagSERVER_STATUS& ss 减少的服务器数据
    void     Decr(const tagSERVER_STATUS& ss);
    /// 增加连接量
    void     IncrTotal(bool bLoad = true, UInt uIncr = 1);
    /// 减少连接量
    void     DecrTotal(bool bLoad = true, UInt uDecr = 1);
    /// 增加有效量
    void     IncrOnline(bool bLoad = false, UInt uIncr = 1);
    /// 减少有效量
    void     DecrOnline(bool bLoad = false, UInt uDecr = 1);
    /// 连接量和在线量清零
    void     Zero(void);
    /// 重置所有数据
    void     Reset(void);

    void     SetUpdate(void);
    void     ClearOnline(bool bTotal = true);
    /// 解除告警或者异常状态
    void     Clear(bool bTotal = true);
    /// 清除正常负载
    void     ClearLoad(void);
    /// 设置繁忙状态
    void     BusyLoad(void);
    /// 设置满载状态
    void     FullLoad(void);
    /// 设置超负荷状态
    void     OverLoad(void);
    /// 设置告警状态
    void     WarnLoad(void);
    /// 设置异常状态
    void     MayDay(void);
    /// 判断是否繁忙
    bool     IsBusyLoad(bool bExact = true);
    /// 判断是否满载
    bool     IsFullLoad(bool bExact = true);
    /// 判断是否负载超负荷
    bool     IsOverLoad(bool bExact = true);
    /// 判断是否告警
    bool     IsWarnLoad(bool bExact = true);
    /// 判断是否异常
    bool     IsMayDay(void);
    ///
    bool     IsUpdated(void);
};
typedef tagSERVER_INFO SERVER_INFO, *PSERVER_INFO;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 不包含地址的服务器信息结构定义
struct tagSERVER_NOADDR : public tagSERVER_INFO
{
public:
    /// 包含地址信息的个数=0
    static Int    Count(void);
    static size_t Length(void);
public:
    tagSERVER_NOADDR(void);
    ~tagSERVER_NOADDR(void);

    size_t AddrLength(void);
    /// 按特定状态要求读写
    /// @param[in] CStream& Stream数据流
    /// @param[in] UShort us特定状态
    void   Addr(CStream& Stream, UShort us = (UShort)STATUSU_XLINKSYNC);
};
typedef tagSERVER_NOADDR SERVER_NOADDR, *PSERVER_NOADDR;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 包含地址的服务器信息结构定义
template <size_t stCount>
struct tagSERVER_ADDR : public tagSERVER_INFO
{
public:
    /// 包含地址信息的个数
    static Int    Count(void);
    static size_t Length(void);
public:
    tagSERVER_ADDR(void);
    ~tagSERVER_ADDR(void);

    size_t AddrLength(void);
    /// 按特定状态要求读写
    /// @param[in] CStream& Stream数据流
    /// @param[in] UShort us特定状态
    void   Addr(CStream& Stream, UShort us = (UShort)STATUSU_XLINKSYNC);
public:
    CNetAddr   NetAddr[stCount];
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// 这里服务器数据的差别只是网络地址数量的多少, 所以使用简单的模板结构来描述各服务器的信息结构
// 如果特定的服务器需要包含特殊的数据(例如包含服务器名称的), 另外声明服务器信息结构
// COMMON_INDEX
enum COMMON_INDEX 
{
    COMMONI_ANY,
    COMMONI_COUNT,
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// 服务器信息结构定义
typedef tagSERVER_ADDR<COMMONI_COUNT>   COMMON_ADDR, *PCOMMON_ADDR;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// BALANCE_INDEX
enum BALANCE_INDEX
{
    BALANCEI_EXTERNAL,
    BALANCEI_COUNT,
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// 授权均衡服务器信息结构定义
typedef tagSERVER_ADDR<BALANCEI_COUNT> BALANCE_ADDR, *PBALANCE_ADDR;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// AUTHOR_INDEX
enum AUTHOR_INDEX 
{
    AUTHORI_EXTERNAL,
    AUTHORI_MASTER,   // 签证流程
    AUTHORI_AUTHORDB, // 授权数据服务器地址
    AUTHORI_COUNT,
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// 授权网关服务器信息结构定义
typedef tagSERVER_ADDR<AUTHORI_COUNT>  AUTHOR_ADDR,  *PAUTHOR_ADDR;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// MASTER_INDEX
enum MASTER_INDEX 
{
    MASTERI_INTERNAL, // TCP监听业务功能和业务网关服务器地址
    MASTERI_AUTHOR,   // 签证流程
    MASTERI_MASTERDB, // 业务数据服务器地址
    MASTERI_COUNT,
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// 业务管理服务器信息结构定义
typedef tagSERVER_ADDR<MASTERI_COUNT>   MASTER_ADDR,   *PMASTER_ADDR;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// SERVICE_INDEX
enum SERVICE_INDEX 
{
    SERVICEI_MASTER,   // 业务管理服务器地址
    SERVICEI_MASTERDB, // 业务数据服务器地址
    SERVICEI_COUNT,
};
typedef tagSERVER_ADDR<SERVICEI_COUNT>   SERVICE_ADDR,   *PSERVICE_ADDR;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// GATE_INDEX
enum GATE_INDEX 
{
    GATEI_EXTERNAL,
    GATEI_AUTHOR,    // 签证流程
    GATEI_COUNT,
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// 业务网关服务器信息结构定义
typedef tagSERVER_ADDR<GATEI_COUNT>   GATE_ADDR,   *PGATE_ADDR;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 服务器信息映射表结构定义
template <typename V>
struct tagSERVER_MAP : public MObject
{
public:
    /// 单个服务器数据的key-value数据结构
    struct tagSVR_PAIR : public MObject
    {
    public:
        void Serialize(CStream& Stream);
    public:
        ULLong   ullKey;
        V        Value;
    };
    typedef struct tagSVR_PAIR                SVR_PAIR, *PSVR_PAIR;
    typedef CTMap<ULLong, V>                  SVR_MAP;
    typedef typename CTMap<ULLong, V>::PAIR   SVR_MAP_PAIR;
public:
    /// 更新STATUSU_LINK&STATUSU_SYNC为STATUSU_OKAY状态, STATUSU_UNLINK状态删除
    void  Update(void);

    /// 按特定状态要求读取服务器数据
    /// @param[in] CStream& Stream数据流
    /// @param[in] UShort us特定状态
    /// @return 有读取或者写入数据返回true, 否则返回false
    bool  Read(CStream& Stream, UShort us = (UShort)STATUSU_XLINKSYNC);

    /// 按特定状态要求写入服务器数据
    /// @param[in] CStream& Stream数据流
    /// @param[in] UShort us特定状态
    /// @return 有读取或者写入数据返回true, 否则返回false
    bool  Write(CStream& Stream, SVR_MAP_PAIR* pPair, UShort us = (UShort)STATUSU_XLINKSYNC);
public:
    SVR_MAP       SvrMap;
    CSyncLock     SvrLock;
};
typedef tagSERVER_MAP<SERVER_NOADDR>        SVR_SERVER_MAP,        *PSVR_SERVER_MAP;
typedef tagSERVER_MAP<COMMON_ADDR>          SVR_COMMON_MAP,        *PSVR_COMMON_MAP;
typedef tagSERVER_MAP<BALANCE_ADDR>         SVR_BALANCE_MAP,       *PSVR_BALANCE_MAP;
typedef tagSERVER_MAP<AUTHOR_ADDR>          SVR_AUTHOR_MAP,        *PSVR_AUTHOR_MAP;
typedef tagSERVER_MAP<MASTER_ADDR>          SVR_MASTER_MAP,        *PSVR_MASTER_MAP;
typedef tagSERVER_MAP<SERVICE_ADDR>         SVR_SERVICE_MAP,       *PSVR_SERVICE_MAP;
typedef tagSERVER_MAP<GATE_ADDR>            SVR_GATE_MAP,          *PSVR_GATE_MAP;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
/// 服务器信息交换链定义
template <typename TCHAIN>
struct tagSERVER_CHAIN : public MObject
{
public:
    tagSERVER_CHAIN(void);
    ~tagSERVER_CHAIN(void);

    void      Init(Int nHashSize = MAP_HASH_MIN);
    void      Exit(void);

    TCHAIN&   GetCurr(void);
    TCHAIN&   GetNext(void);
    TCHAIN&   GetNextClone(void);

    void      Swap(void);
public:
    UInt        uIndex;
    TCHAIN      Chain[2];
    CSyncLock   Lock;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "servermap.inl"

#endif // __SERVER_MAP_H__
